package com.spring.theory.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import lombok.extern.slf4j.Slf4j;

/**
 * JdkProxy 基本使用
 * - 只针对接口进行代理
 *
 * @author H
 * @version 1.0
 * @date 2023-12-29 16:53
 */
@Slf4j
public class JdkProxy {

    /**
     * jdk代理接口
     */
    interface TJdkProxy {
        void jdkProxyTest(String name);
    }

    /**
     * 它与代理对象是兄弟关系；
     * 目标对象可以是final的 无子类对象；
     */
    static final class Target implements TJdkProxy {
        @Override
        public void jdkProxyTest(String name) {
            log.info("jdk proxy target test...method:{}", name);
        }
    }

    public static void main(String[] args) {
        //待增强对象
        Target target = new Target();

        //加载类用来加载代理类内部在运行期间，动态生成的字节码
        ClassLoader classLoader = JdkProxy.class.getClassLoader();
        /**
         * 1. 生成代理对象 与目标对象是兄弟关系
         * 2. 用接口来接收实例对象；依赖抽象而不依赖具体，从而更具扩展性
         */
        TJdkProxy proxy = (TJdkProxy) Proxy.newProxyInstance(classLoader, new Class[]{TJdkProxy.class}, new InvocationHandler() {
            /**
             * proxy：代理对象本身；
             * method：正在执行的方法对象；
             * args：方法传来的实际参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                log.info("proxy test...before");
                //方法反射执行目标对象方法
                Object result = method.invoke(target, args);
                log.info("proxy test...after");
                return result;
            }
        });
        proxy.jdkProxyTest("proxy jdk");

    }


}
